package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.JiangsuIndividualRecordSheet;
import com.file.bo.socialsecurity.JiangsuInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class JiangsuSocialSecurityPdfParser extends BasePdfParser {

    public ResponseData<String> parseJiangsuSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseJiangsuSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            if (filePath.contains("cbzm")) {
                JiangsuInsuranceParticipation jiangsuInsuranceParticipation = parseJiangsuInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(jiangsuInsuranceParticipation);
            } else if (filePath.contains("qyd")) {//NOSONAR
                JiangsuIndividualRecordSheet jiangsuIndividualRecordSheet = parseJiangsuIndividualRecordSheet(filePath);//NOSONAR
                json = JsonUtils.convertObjectToJson(jiangsuIndividualRecordSheet);//NOSONAR
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseJiangsuSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseJiangsuSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseJiangsuSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private JiangsuIndividualRecordSheet parseJiangsuIndividualRecordSheet(String filePath) {
        JiangsuIndividualRecordSheet jiangsuIndividualRecordSheet = parseJiangsuIndividualRecordSheetHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, jiangsuIndividualRecordSheet);
        return jiangsuIndividualRecordSheet;
    }

    private JiangsuIndividualRecordSheet parseJiangsuIndividualRecordSheetHeader(String filePath) {
        JiangsuIndividualRecordSheet jiangsuIndividualRecordSheet = new JiangsuIndividualRecordSheet();
        String pdfText = getPdfTextByStripper2(filePath).replace(System.getProperty("line.separator", "\n"), "");
        ;
        // 2021年7月至2021年12月
        String recordPeriod = "";
        if (pdfText.contains("（企业职工）（") && pdfText.contains("）个人基本信息")) {
            recordPeriod = pdfText.substring(pdfText.indexOf("（企业职工）（") + 7, pdfText.indexOf("）个人基本信息"));
        } else {
            Pattern pattern = Pattern.compile("\\d{4}年\\d{1,2}月至\\d{4}年\\d{1,2}");
            Matcher matcher = pattern.matcher(pdfText);
            if (matcher.find()) {
                recordPeriod = matcher.group();
            }
        }

        String socialInsuranceAgencyName = pdfText.substring(pdfText.lastIndexOf("社会保险经办机构名称：") + 11, pdfText.lastIndexOf("打印时间")).trim();

        String printTime = pdfText.substring(pdfText.lastIndexOf("打印时间：") + 5, pdfText.lastIndexOf("联系电话")).trim();

        String telephoneNumber = pdfText.substring(pdfText.lastIndexOf("联系电话：") + 5, pdfText.lastIndexOf("地址")).trim();
        String address = "";
        if (pdfText.contains("<电子签章>")) {
            address = pdfText.substring(pdfText.lastIndexOf("地址：") + 3, pdfText.lastIndexOf("<电子签章>")).trim();
        } else {
            address = pdfText.substring(pdfText.lastIndexOf("地址：") + 3).trim();
        }

        jiangsuIndividualRecordSheet.setRecordPeriod(recordPeriod);
        jiangsuIndividualRecordSheet.setSocialInsuranceAgencyName(socialInsuranceAgencyName);
        jiangsuIndividualRecordSheet.setPrintTime(printTime);
        jiangsuIndividualRecordSheet.setTelephoneNumber(telephoneNumber);
        jiangsuIndividualRecordSheet.setAddress(address);
        return jiangsuIndividualRecordSheet;
    }

    private void parseListToBO(List<List<String>> rowList, JiangsuInsuranceParticipation jiangsuInsuranceParticipation) {

        JiangsuInsuranceParticipation.ParticipationInSocialInsurance participationInSocialInsurance = new JiangsuInsuranceParticipation.ParticipationInSocialInsurance();
        jiangsuInsuranceParticipation.setParticipationInSocialInsurance(participationInSocialInsurance);
        List<JiangsuInsuranceParticipation.PaymentStatus> paymentStatusList = new ArrayList<>();

        Set<JiangsuInsuranceParticipation.PaymentStatus> paymentStatusSet = new LinkedHashSet<>();
        jiangsuInsuranceParticipation.setPaymentStatusList(paymentStatusList);

        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);

            if (StringUtils.isBlank(cellList.get(0))) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "姓名")) {
                sectionName = "姓名";
            } else if (StringUtils.equals(cellList.get(0), "共1页,第1页") || StringUtils.equals(cellList.get(0), "参加社会保险基本情况")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "险种")) {
                sectionName = "险种";
            } else if (StringUtils.equals(cellList.get(0), "参保状态")) {
                sectionName = "参保状态";
            } else if (StringUtils.equals(cellList.get(0), "现参保单位全称")) {
                sectionName = "现参保单位全称";
            } else if (StringUtils.contains(cellList.get(0), "出具证明前")) {
                sectionName = "出具证明前";
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "姓名":
                    if (!StringUtils.equals(cellList.get(0), "姓名")) {
                        continue;
                    }
                    jiangsuInsuranceParticipation.setName(cellList.get(1));
                    jiangsuInsuranceParticipation.setSocialSecurityNumber(cellList.get(3));
                    jiangsuInsuranceParticipation.setGender(cellList.get(5));
                    break;
                case "险种":
                    List<String> insuranceTypeList = new ArrayList<>();
                    insuranceTypeList.add(cellList.get(1));
                    insuranceTypeList.add(cellList.get(2));
                    insuranceTypeList.add(cellList.get(3));
                    jiangsuInsuranceParticipation.getParticipationInSocialInsurance().setInsuranceTypeList(insuranceTypeList);
                    break;
                case "参保状态":
                    List<String> insuranceStatusList = new ArrayList<>();
                    insuranceStatusList.add(cellList.get(1));
                    insuranceStatusList.add(cellList.get(2));
                    insuranceStatusList.add(cellList.get(3));
                    jiangsuInsuranceParticipation.getParticipationInSocialInsurance().setInsuranceStatusList(insuranceStatusList);
                    break;
                case "现参保单位全称":
                    jiangsuInsuranceParticipation.getParticipationInSocialInsurance().setCurrentInsuredUnitFullName(cellList.get(1));
                    jiangsuInsuranceParticipation.getParticipationInSocialInsurance().setCurrentInsuredLocation(cellList.get(3));
                    break;
                case "出具证明前":
                    if (cellList.get(0).matches("\\d{4}")) {
                        JiangsuInsuranceParticipation.PaymentStatus paymentStatus = new JiangsuInsuranceParticipation.PaymentStatus();
                        paymentStatus.setYear(cellList.get(0));
                        paymentStatus.setMonth(cellList.get(1));
                        paymentStatus.setUnitFullName(cellList.get(2));

                        JiangsuInsuranceParticipation.EndowmentInsurance endowmentInsurance = new JiangsuInsuranceParticipation.EndowmentInsurance();
                        endowmentInsurance.setPaymentBase(cellList.get(3));
                        endowmentInsurance.setIndividualPayment(cellList.get(4));
                        paymentStatus.setEndowmentInsurance(endowmentInsurance);

                        JiangsuInsuranceParticipation.UnemploymentInsurance unemploymentInsurance = new JiangsuInsuranceParticipation.UnemploymentInsurance();
                        unemploymentInsurance.setPaymentBase(cellList.get(5));
                        unemploymentInsurance.setIndividualPayment(cellList.get(6));
                        paymentStatus.setUnemploymentInsurance(unemploymentInsurance);

                        JiangsuInsuranceParticipation.EmploymentInjuryInsurance employmentInjuryInsurance = new JiangsuInsuranceParticipation.EmploymentInjuryInsurance();
                        employmentInjuryInsurance.setPaymentBase(cellList.get(7));
                        paymentStatus.setEmploymentInjuryInsurance(employmentInjuryInsurance);

                        paymentStatus.setNotes(cellList.get(8));

                        paymentStatusSet.add(paymentStatus);
                        break;
                    }
            }
        }

        paymentStatusList.addAll(paymentStatusSet);
    }

    private void parseListToBO(List<List<String>> rowList, JiangsuIndividualRecordSheet jiangsuIndividualRecordSheet) {
        JiangsuIndividualRecordSheet.PersonalInformation personalInformation = new JiangsuIndividualRecordSheet.PersonalInformation();
        JiangsuIndividualRecordSheet.FirstInsuredDate firstInsuredDate = new JiangsuIndividualRecordSheet.FirstInsuredDate();
        personalInformation.setFirstInsuredDate(firstInsuredDate);
        jiangsuIndividualRecordSheet.setPersonalInformation(personalInformation);

        JiangsuIndividualRecordSheet.PaymentDetails paymentDetails = new JiangsuIndividualRecordSheet.PaymentDetails();
        JiangsuIndividualRecordSheet.PersonalMonthlyPaymentBase personalMonthlyPaymentBase = new JiangsuIndividualRecordSheet.PersonalMonthlyPaymentBase();
        JiangsuIndividualRecordSheet.PensionPaymentInformation pensionPaymentInformation = new JiangsuIndividualRecordSheet.PensionPaymentInformation();
        JiangsuIndividualRecordSheet.UnemploymentPaymentInformation unemploymentPaymentInformation = new JiangsuIndividualRecordSheet.UnemploymentPaymentInformation();
        JiangsuIndividualRecordSheet.ThisYearPersonalOverduePaymentAmount thisYearPersonalOverduePaymentAmount = new JiangsuIndividualRecordSheet.ThisYearPersonalOverduePaymentAmount();
        JiangsuIndividualRecordSheet.SupplementaryOverTheYearsPaymentMonths supplementaryOverTheYearsPaymentMonths = new JiangsuIndividualRecordSheet.SupplementaryOverTheYearsPaymentMonths();
        JiangsuIndividualRecordSheet.EndOfTheYearActualPaymentMonths endOfTheYearActualPaymentMonths = new JiangsuIndividualRecordSheet.EndOfTheYearActualPaymentMonths();
        JiangsuIndividualRecordSheet.AccumulatedUnpaidMonths accumulatedUnpaidMonths = new JiangsuIndividualRecordSheet.AccumulatedUnpaidMonths();
        paymentDetails.setPersonalMonthlyPaymentBase(personalMonthlyPaymentBase);
        paymentDetails.setPensionPaymentInformation(pensionPaymentInformation);
        paymentDetails.setUnemploymentPaymentInformation(unemploymentPaymentInformation);
        paymentDetails.setThisYearPersonalOverduePaymentAmount(thisYearPersonalOverduePaymentAmount);
        paymentDetails.setSupplementaryOverTheYearsPaymentMonths(supplementaryOverTheYearsPaymentMonths);
        paymentDetails.setEndOfTheYearActualPaymentMonths(endOfTheYearActualPaymentMonths);
        paymentDetails.setAccumulatedUnpaidMonths(accumulatedUnpaidMonths);
        jiangsuIndividualRecordSheet.setPaymentDetails(paymentDetails);

        JiangsuIndividualRecordSheet.PersonalAccountInformation personalAccountInformation = new JiangsuIndividualRecordSheet.PersonalAccountInformation();
        JiangsuIndividualRecordSheet.BasicEndowmentInsurance basicEndowmentInsurance = new JiangsuIndividualRecordSheet.BasicEndowmentInsurance();
        personalAccountInformation.setBasicEndowmentInsurance(basicEndowmentInsurance);
        jiangsuIndividualRecordSheet.setPersonalAccountInformation(personalAccountInformation);

        String sectionName = "";
        int count = 0;

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (count > 1) {
                break;
            }
            if (StringUtils.equals(cellList.get(0), "姓名")) {
                count++;
                sectionName = "姓名";
            } else if (StringUtils.equals(cellList.get(0), "首次参保日期")) {
                sectionName = "首次参保日期";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(0), "缴费情况", "个人账户情况", "基本养老保险", "工伤保险定期待遇情况")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "个人月缴费基数")) {
                sectionName = "个人月缴费基数";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "本年个人补缴欠费金额")) {
                sectionName = "本年个人补缴欠费金额";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "养老")) {
                continue;
            } else if (StringUtils.equals(cellList.get(0), "截至上年末个人账户累计储存额")) {
                sectionName = "截至上年末个人账户累计储存额";
                continue;
            } else if (StringUtils.equals(cellList.get(0), "伤残等级")) {
                sectionName = "伤残等级";
                continue;
            }

            switch (sectionName) {//NOSONAR
                case "姓名":
                    personalInformation.setName(cellList.get(1));
                    personalInformation.setUnitName(cellList.get(3));
                    personalInformation.setSocialSecurityNumber(cellList.get(5));
                    break;
                case "首次参保日期":
                    firstInsuredDate.setPension(cellList.get(2));
                    firstInsuredDate.setUnemployment(cellList.get(3));
                    firstInsuredDate.setWorkRelatedInjury(cellList.get(4));
                    break;
                case "个人月缴费基数":
                    personalMonthlyPaymentBase.setPension(cellList.get(0));
                    personalMonthlyPaymentBase.setUnemployment(cellList.get(1));
                    personalMonthlyPaymentBase.setWorkRelatedInjury(cellList.get(2));
                    pensionPaymentInformation.setUnitPayment(cellList.get(3));
                    pensionPaymentInformation.setPersonalPayment(cellList.get(4));
                    unemploymentPaymentInformation.setUnitPayment(cellList.get(5));
                    unemploymentPaymentInformation.setPersonalPayment(cellList.get(6));
                    paymentDetails.setWorkRelatedInjuryPaymentInformation(cellList.get(7));
                    break;
                case "本年个人补缴欠费金额":
                    thisYearPersonalOverduePaymentAmount.setPension(cellList.get(0));
                    thisYearPersonalOverduePaymentAmount.setUnemployment(cellList.get(1));
                    supplementaryOverTheYearsPaymentMonths.setPension(cellList.get(2));
                    supplementaryOverTheYearsPaymentMonths.setUnemployment(cellList.get(3));
                    endOfTheYearActualPaymentMonths.setPension(cellList.get(4));
                    endOfTheYearActualPaymentMonths.setUnemployment(cellList.get(5));
                    accumulatedUnpaidMonths.setPension(cellList.get(6));
                    accumulatedUnpaidMonths.setUnemployment(cellList.get(7));
                    break;
                case "截至上年末个人账户累计储存额":
                    basicEndowmentInsurance.setEndOfLastYearAccumulatedPersonalAccountSavings(cellList.get(0));
                    basicEndowmentInsurance.setCurrentYearAccountingAmount(cellList.get(1));
                    basicEndowmentInsurance.setCurrentYearPersonalAccountExpenditureAmount(cellList.get(2));
                    basicEndowmentInsurance.setCurrentYearAccountingInterest(cellList.get(3));
                    basicEndowmentInsurance.setEndOfThisYearAccumulatedAccountStorageAmount(cellList.get(4));
                    break;
            }
        }
    }


    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                if (entry.getKey() > 1) {
                    rectangle.setTop(rectangle.getTop());
                }
                rectangle.setBottom(rectangle.getBottom() + 500);
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    private JiangsuInsuranceParticipation parseJiangsuInsuranceParticipation(String filePath) {//NOSONAR
        JiangsuInsuranceParticipation jiangsuInsuranceParticipation = new JiangsuInsuranceParticipation();
        String pdfText = getPdfTextByStripper(filePath).replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);

        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, jiangsuInsuranceParticipation);

        int index = 0;
        if (pdfText.contains("共3页") && pdfText.contains("第2页")) {
            boolean arrivedSecondTable = false;

            for (List<String> cellList : rowList) {
                if (cellList.get(0).contains("共3页,第2页")) {
                    arrivedSecondTable = true;
                    index++;
                }


                if (arrivedSecondTable && index == 2) {

                    if (cellList.get(0).matches("\\d{4}")) {  //NOSONAR
                        JiangsuInsuranceParticipation.PaymentStatus paymentStatus = new JiangsuInsuranceParticipation.PaymentStatus();
                        paymentStatus.setYear(cellList.get(0));
                        paymentStatus.setMonth(cellList.get(1));
                        paymentStatus.setUnitFullName(cellList.get(2));

                        JiangsuInsuranceParticipation.EndowmentInsurance endowmentInsurance = new JiangsuInsuranceParticipation.EndowmentInsurance();
                        endowmentInsurance.setPaymentBase(cellList.get(3));
                        endowmentInsurance.setIndividualPayment(cellList.get(4));
                        paymentStatus.setEndowmentInsurance(endowmentInsurance);

                        JiangsuInsuranceParticipation.UnemploymentInsurance unemploymentInsurance = new JiangsuInsuranceParticipation.UnemploymentInsurance();
                        unemploymentInsurance.setPaymentBase(cellList.get(5));
                        unemploymentInsurance.setIndividualPayment(cellList.get(6));
                        paymentStatus.setUnemploymentInsurance(unemploymentInsurance);

                        JiangsuInsuranceParticipation.EmploymentInjuryInsurance employmentInjuryInsurance = new JiangsuInsuranceParticipation.EmploymentInjuryInsurance();
                        employmentInjuryInsurance.setPaymentBase(cellList.get(7));
                        paymentStatus.setEmploymentInjuryInsurance(employmentInjuryInsurance);

                        paymentStatus.setNotes(cellList.get(8));

                        jiangsuInsuranceParticipation.getPaymentStatusList().add(paymentStatus);
                    }
                }
            }
        }

        String notes = null;
        String printTime = null;
        try {
            notes = pdfText.substring(pdfText.lastIndexOf("说明：") + 3, pdfText.lastIndexOf("（盖章）")).trim();
            printTime = pdfText.substring(pdfText.lastIndexOf("打印时间：") + 5).trim();
        } catch (Exception e) {
            notes = pdfText.substring(pdfText.lastIndexOf("说明：") + 3, pdfText.lastIndexOf("打印时间：")).trim();
            printTime = pdfText.substring(pdfText.lastIndexOf("打印时间：") + 5, pdfText.lastIndexOf("（签章）")).trim();
        }

        jiangsuInsuranceParticipation.setDescription(notes);
        jiangsuInsuranceParticipation.setPrintTime(printTime);

        return jiangsuInsuranceParticipation;
    }


    public static void main(String[] args) {
//        String filePath = "D:\\data\\file\\socialsecurity\\江苏\\app-gjzwfw-dzsb_qyd.pdf";
//        String json;
//        JiangsuSocialSecurityPdfParser jiangsuSocialSecurityPdfParser = new JiangsuSocialSecurityPdfParser();
//         json = jiangsuSocialSecurityPdfParser.parseJiangsuSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println("json = " + json);

//        filePath = "D:\\data\\file\\socialsecurity\\江苏\\20240708\\app-gjzwfw-dzsb_cbzm.pdf";
//        json = jiangsuSocialSecurityPdfParser.parseJiangsuSocialSecurityPdfToJson("", filePath).getData();
//        System.out.println("json = " + json);
    }

}
